import { Injectable, NestMiddleware, UnauthorizedException } from '@nestjs/common';
import { Request, Response, NextFunction } from 'express';
import { AuthService } from './auth.service';
import { AuthConfig } from './auth.config';

@Injectable()
export class TokenMiddleware implements NestMiddleware {
  constructor(private readonly authService: AuthService) {}

  async use(req: Request, res: Response, next: NextFunction) {
    // 检查是否在白名单中
    if (this.isInWhiteList(req.path)) {
      return next();
    }

    // 开发环境可选禁用
    if (process.env.NODE_ENV === 'development' && AuthConfig.disableInDevelopment) {
      return next();
    }

    // 从请求头获取token
    const token = this.extractTokenFromHeader(req);
    if (!token) {
      throw new UnauthorizedException('缺少访问令牌');
    }

    // 验证token
    const payload = await this.authService.validateToken(token);
    if (!payload) {
      throw new UnauthorizedException('无效的访问令牌');
    }

    // 可选：检查IP地址
    if (AuthConfig.checkIp && payload.ip && payload.ip !== req.ip) {
      throw new UnauthorizedException('IP地址不匹配');
    }

    // 将用户信息附加到请求对象
    req['user'] = payload;
    
    next();
  }

  /**
   * 从请求头中提取token
   */
  private extractTokenFromHeader(request: Request): string | undefined {
    const [type, token] = request.headers.authorization?.split(' ') ?? [];
    return type === 'Bearer' ? token : undefined;
  }

  /**
   * 检查请求路径是否在白名单中
   */
  private isInWhiteList(path: string): boolean {
    return AuthConfig.whiteList.some(whitePath => {
      // 精确匹配
      if (whitePath === path) {
        return true;
      }
      
      // 前缀匹配
      if (whitePath.endsWith('*') && path.startsWith(whitePath.slice(0, -1))) {
        return true;
      }
      
      return false;
    });
  }
}